package handler

import (
	"net/http"

	"database/sql"

	"gitee.com/hp-huiw/family-expense-api/internal/dto"
	"gitee.com/hp-huiw/family-expense-api/internal/service"
	"github.com/gin-gonic/gin"
)

type JourneyIncomeExpenseDetailHandler interface {
	QueryExistingDistinctYears(ctx *gin.Context)
	QueryListByJourney(ctx *gin.Context)
	QueryDetails(ctx *gin.Context)
	QueryCoordinates(ctx *gin.Context)
	Add(ctx *gin.Context)
	Update(ctx *gin.Context)
	Delete(ctx *gin.Context)
}

func NewJourneyIncomeExpenseDetailHandler(db *sql.DB) JourneyIncomeExpenseDetailHandler {
	return &journeyIncomeExpenseDetailHandler{
		journeyIncomeExpenseDetailService: service.NewJourneyIncomeExpenseDetailService(db),
	}
}

// Matches /query-existing-distinct-years of http get action.
func (h *journeyIncomeExpenseDetailHandler) QueryExistingDistinctYears(ctx *gin.Context) {
	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	result, err := h.journeyIncomeExpenseDetailService.QueryExistingDistinctYears(c, accountGroupID)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /query-list-by-journey of http get action.
func (h *journeyIncomeExpenseDetailHandler) QueryListByJourney(ctx *gin.Context) {
	journeyID := ctx.Query("journeyId")

	c := ctx.Request.Context()
	var params dto.IncomeExpenseDetailQueryArgumentRequest
	ctx.Bind(&params)
	params.AccountGroupID = GetClaims(ctx).AccountGroupID

	result, _ := h.journeyIncomeExpenseDetailService.Query(c, journeyID, params)

	SendDataResponse(ctx, result)
}

// Matches /query-details of http get action.
func (h *journeyIncomeExpenseDetailHandler) QueryDetails(ctx *gin.Context) {
	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	id := ctx.Query("id")
	result, err := h.journeyIncomeExpenseDetailService.QueryDetails(c, accountGroupID, id)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /query-coordinates of http get action.
func (h *journeyIncomeExpenseDetailHandler) QueryCoordinates(ctx *gin.Context) {
	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	year := ctx.Query("year")
	result, err := h.journeyIncomeExpenseDetailService.QueryCoordinates(c, accountGroupID, year)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /add of http post action.
func (h *journeyIncomeExpenseDetailHandler) Add(ctx *gin.Context) {
	accountGroupID := GetClaims(ctx).AccountGroupID
	var postedData dto.JourneyIncomeExpenseDetailResquest

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	claims := GetClaims(ctx)
	err := h.journeyIncomeExpenseDetailService.Add(c, &postedData, accountGroupID, claims.Username)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Matches /update of http post action.
func (h *journeyIncomeExpenseDetailHandler) Update(ctx *gin.Context) {
	var postedData dto.JourneyIncomeExpenseDetailResquest

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	claims := GetClaims(ctx)
	err := h.journeyIncomeExpenseDetailService.Update(c, claims.AccountGroupID, claims.Username, &postedData)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Matches /delete of http post action.
func (h *journeyIncomeExpenseDetailHandler) Delete(ctx *gin.Context) {
	var postedData struct {
		ID string `json:"id"`
	}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	err := h.journeyIncomeExpenseDetailService.Delete(c, accountGroupID, []string{postedData.ID})

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Container of JourneyIncomeExpenseDetailHandler functions.
type journeyIncomeExpenseDetailHandler struct {
	journeyIncomeExpenseDetailService service.JourneyIncomeExpenseDetailService
}
